在 Mac 和 iOS 平台中,内存泄漏通常是由未释放的指针引起的。传统上,检查您的分配、复制和保留以确保每个都有相应的发布消息一直是最重要的。
Xcode 4.2 附带的工具链在最新版本的LLVM 编译器中引入了自动引用计数 (ARC),通过让编译器为您管理您的内容,完全解决了这个问题。这很酷,它确实减少了许多不必要的、平凡的开发时间,并防止了许多粗心的内存泄漏,这些泄漏很容易通过适当的保留/释放平衡来修复。当您为 Mac 和 iOS 应用程序启用 ARC 时,甚至自动释放池也需要以不同的方式进行管理(因为您不应再分配自己的NSAutoreleasePools)。
NSAutoreleasePool
但是还有哪些 其他 内存泄漏 不能 阻止我仍然需要提防?
作为奖励,Mac OS X 和 iOS 上的 ARC 和 Mac OS X 上的垃圾收集有什么区别?
您仍然需要注意的与内存相关的主要问题是保留周期。当一个对象具有指向另一个对象的强指针,但目标对象具有指向原始对象的强指针时,就会发生这种情况。即使删除了对这些对象的所有其他引用,它们仍然会相互保持并且不会被释放。这也可以通过一系列对象间接发生,这些对象链中的最后一个对象可能指向较早的对象。
正是出于这个原因,存在__unsafe_unretained和__weak所有权限定符。前者不会保留它指向的任何对象,但会保留该对象消失并指向坏内存的可能性,而后者不保留该对象并在其目标被释放时自动将其自身设置为 nil。在这两者中,__weak通常在支持它的平台上是首选。
__unsafe_unretained
__weak
您可以将这些限定符用于委托等事物,您不希望对象保留其委托并可能导致循环。
另一个与内存相关的重要问题是处理 Core Foundation 对象和malloc()为char*. ARC 不管理这些类型,只管理 Objective-C 对象,因此您仍然需要自己处理它们。Core Foundation 类型可能特别棘手,因为有时它们需要桥接以匹配 Objective-C 对象,反之亦然。这意味着在 CF 类型和 Objective-C 之间进行桥接时,需要从 ARC 来回传输控制。添加了一些与此桥接相关的关键字,Mike Ash 在他冗长的 ARC 文章中对各种桥接案例进行了很好的描述。
malloc()
char*
除此之外,还有其他一些不太常见但仍有潜在问题的案例,已发布的规范对此进行了详细介绍。
许多新行为基于只要有指向它们的强指针就保留对象,这与 Mac 上的垃圾收集非常相似。但是,技术基础却大相径庭。这种内存管理风格不是让垃圾收集器进程定期运行以清理不再指向的对象,而是依赖于我们在 Objective-C 中都需要遵守的严格的保留/释放规则。
ARC 只需将我们多年来不得不做的重复性内存管理任务转移到编译器上,这样我们就不必再担心它们了。这样,您就不会遇到在垃圾收集平台上遇到的停止问题或锯齿状内存配置文件。我在垃圾收集的 Mac 应用程序中经历了这两种情况,并渴望了解它们在 ARC 下的表现。
有关垃圾收集与 ARC 的更多信息,请参阅Chris Lattner 在 Objective-C 邮件列表上的这个非常有趣的回复,他在其中列出了 ARC 相对于 Objective-C 2.0 垃圾收集的许多优点。我遇到了他描述的几个 GC 问题。